package net.gazhi.delonix.rbac.entity;

import java.lang.reflect.Method;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Transient;

import org.springframework.web.method.HandlerMethod;

/**
 * 操作<br>
 * 对应Spring MVC 的请求处理Action方法
 * 
 * @author Jeffrey Lin
 *
 */
@Entity(name = DX_TABLE.dx_action)
public class Action implements Comparable<Action> {

	/**
	 * 生成功能点 ID
	 * 
	 * @see #generateActionId(String)
	 */
	public static int generateActionId(HandlerMethod hm) {
		Method method = hm.getMethod();
		Class<?> clazz = method.getDeclaringClass();
		String qualifiedMethodName = clazz.getName() + "." + method.getName();
		return generateActionId(qualifiedMethodName);
	}

	/**
	 * 使用 方法全名的 HashCode 绝对值作为 actionId，确保权限配置关联的 actionId 不变<br>
	 * 在设计 controller 时，同一个 controller 类里，不要出现同名的 haldler 方法<br>
	 * 点背的情况下，很可能会出现不同 fullMethodName 计算出来的 actionId 一样，改个名字就好了
	 * 
	 * @param fullMethodName
	 * @return
	 */
	public static int generateActionId(String qualifiedMethodName) {
		return Math.abs(qualifiedMethodName.hashCode());
	}

	@Id
	private int id;

	@Column(name = "show_order")
	private int showOrder;

	@Column(name = "name")
	private String name;

	@Column
	private String path;

	@Column
	private int level;

	/**
	 * 接口方法名，包括类名，不包括参数表
	 */
	@Transient
	private String qualifiedMethodName;

	@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
	@JoinColumn(name = "controller_id", nullable = false)
	private Controller controller;

	public Action() {
	}

	public Action(String qualifiedMethodName, int showOrder, String name, String path, int level, Controller controller) {
		this.id = generateActionId(qualifiedMethodName);
		this.qualifiedMethodName = qualifiedMethodName;
		this.showOrder = showOrder;
		this.name = name;
		this.path = path;
		this.level = level;
		this.controller = controller;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public int getShowOrder() {
		return showOrder;
	}

	public void setShowOrder(int showOrder) {
		this.showOrder = showOrder;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public String getQualifiedMethodName() {
		return qualifiedMethodName;
	}

	public Controller getController() {
		return controller;
	}

	public void setController(Controller controller) {
		this.controller = controller;
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	@Override
	public int compareTo(Action target) {
		int i = this.getController().compareTo(target.getController());
		if (i == 0) {
			i = Integer.compare(this.showOrder, target.showOrder);
		}
		return i;
	}

}
